#include "slShader.hh"

using namespace std;

slShader::slShader()
{
	
}

bool slShader::_checkCompilation(GLuint shaderID)
{
	GLint compilationStatus = 0;
 
    glGetShaderiv(shaderID, GL_COMPILE_STATUS, &compilationStatus);
    if ( compilationStatus != GL_TRUE )
    {
        GLint logLength = 0;
        GLchar* log = NULL;
 
        glGetShaderiv(shaderID, GL_INFO_LOG_LENGTH, &logLength);
 
        log = new GLchar[logLength];
        glGetShaderInfoLog(shaderID, logLength, &logLength, log);
        cerr << "Shader compilation error: " << endl;
        cerr << log << endl;
        delete[] log; 

        return false;
    }
 
    return true;
}

bool slShader::loadShader(const std::string &vertFile, const std::string &fragFile)
{
	ifstream vertex(vertFile.c_str());
	ifstream fragment(fragFile.c_str());

	if (!vertex.good() || !fragment.good())
	{
		cerr << "Error while loading shaders from disk" << endl; 
		vertex.close();
		fragment.close();
		return false;
	}

	string buffer;

	while (vertex)
	{
		getline(vertex, buffer);
		_vertexString += buffer + "\n";
	}

	buffer = "";

	while (fragment)
	{
		getline(fragment, buffer);
		_fragmentString += buffer + "\n";	
	}

	vertex.close();
	fragment.close();

	if ((fragID = glCreateShader(GL_FRAGMENT_SHADER)) == 0)
	{
		cerr << "Error while creating fragment shader" << endl;
		return false;
	}

	if ((vertID = glCreateShader(GL_VERTEX_SHADER)) == 0)
	{
		cerr << "Error while creating vertex shader" << endl;
		return false;
	}

	const char *toto = _fragmentString.c_str();

	glShaderSource(fragID, 1, (const GLchar **)&toto, NULL);
	glCompileShader(fragID);

	const char *tata = _vertexString.c_str();


	glShaderSource(vertID, 1, (const GLchar **)&tata, NULL);
	glCompileShader(vertID);

	if (!_checkCompilation(vertID) || !_checkCompilation(fragID))
		return false;
	
	programID = glCreateProgram();
	glAttachShader(programID, vertID);
    glAttachShader(programID, fragID);
	glLinkProgram(programID);
	return true;
}

void slShader::begin()
{
 glUseProgram(programID);
}

void slShader::end()
{
glUseProgram(0);
}

bool slShader::loadFromString(const std::string &vert, const std::string &frag)
{
	_vertexString = vert;
	_fragmentString = frag;

	return true;
}

void slShader::setUniformSampler2d(std::string name, int texID)
{
  int texture_location = glGetUniformLocation(programID, name.c_str());
  glUniform1i(texture_location, 0);
}

slShader::~slShader()
{
	glDeleteProgram(programID);
}
